// 1. 安装 axios 包
// 2. 新建 utils/request.js 模块文件
// 3. 引入 axios
// 4. 创建 axios 实例，配置请求基地址
// 5. 默认导出 axios 实例，共外界导入使用

import axios from 'axios'
import { Toast } from 'vant'
import { getToken, removeToken } from './storage'
import router from '@/router/index.js'

const axiosInstance = axios.create({
  // 接口基准地址，配置了基准地址后，发请求时，url就可以省略基准地址，直接写路径即可
  // 比如：baseURL: 'http://www.baidu.com'
  // 发登录请求：
  // 以前： http://www.baidu.com/login
  // 现在： /login
  baseURL: 'http://interview-api-t.itheima.net/'
})

// // 配置请求拦截器
// axiosInstance.interceptors.request.use((config) => {
//   // config 是请求配置对象
//   console.log('请求拦截器-成功处理函数-1')

//   // 一定要返回请求配置对象，不然，axios 就不知道要发啥！往哪里发！

//   // 统一注入token：
//   // 所有的请求在发出去之前，都会先进入请求拦截器成功处理函数，在这里，可以对请求配置做调整
//   // 当 本地存储中 有 token 的时候，才需要加到请求头中
//   const token = getToken()
//   if (token) {
//     config.headers.Authorization = 'Bearer ' + token
//   }
//   return config // 最终的请求配置对象
// }, (err) => {
//   console.log('请求拦截器-失败处理函数-1')
//   console.log(err)
//   // return err
//   // 这个 err 接到的就是上一个请求拦截器处理函数中抛出的异常错误对象
//   // 如果 return 一个新的请求配置，那么就算进入了错误的请求拦截器，还是会基于最新的请求配置，发出这个新的请求
//   // return {
//   //   method: 'get',
//   //   url: 'http://baidu.com/login'
//   // }
//   // throw err
//   return Promise.reject(err)
// })

// // 配置请求拦截器
// axiosInstance.interceptors.request.use((config) => {
//   console.log('请求拦截器-成功处理函数-2')
//   // throw new Error(123)
//   // throw config
//   return config // 最终的请求配置对象
// }, (err) => {
//   console.log('请求拦截器-失败处理函数-2')
//   console.log(err)
//   return Promise.reject(err)
// })

// // 配置请求拦截器
// axiosInstance.interceptors.request.use((config) => {
//   console.log('请求拦截器-成功处理函数-3')
//   return config // 最终的请求配置对象
// }, (err) => {
//   console.log('请求拦截器-失败处理函数-3')
//   console.log(err)
//   return Promise.reject(err)
// })

// // 配置请求拦截器
// axiosInstance.interceptors.request.use((config) => {
//   console.log('请求拦截器-成功处理函数-4')
//   return config // 最终的请求配置对象
// }, (err) => {
//   console.log('请求拦截器-失败处理函数-4')
//   console.log(err)
//   return Promise.reject(err)
// })

// // 配置响应拦截器
// // 第一个参数：成功的响应拦截处理函数
// // 第二个参数：失败的响应拦截处理函数
// axiosInstance.interceptors.response.use((res) => {
//   // 进了成功不一定后面就成功，还是得看 return 的是什么
//   // 这里如果不 return，那么响应数据就是 undefined
//   return res
// }, (err) => {
//   // err 错误对象：包含了错误相关的信息，请求配置、响应数据、响应状态码都在其中

//   console.log('err:', err)

//   if (err.response.status === 401) { // token 无效（没传、传错了、过期了）
//     // 1. 删除token
//     removeToken()
//     // 2. 跳转到登录页
//     router.push({ name: 'LoginPage' })
//     // 3. 友好提示一下，为什么会去登录页
//     Toast('你还没有登录，请重新登录！')

//     // 后面【响应拦截器逻辑】以及【页面的逻辑】还需要执行吗？
//     // 后面的逻辑都不需要执行了，因为已经处理好了，都跳到登录页面去了
//     // 只需要中断链式调用即可（中断Promise链式调用，因为axios就是基于Promise实现的）
//     // 如何中断Promise的链式调用呢？
//     // 说白了，就是返回一个状态永远是pending的Promise
//     return new Promise(() => {})
//   } else {
//     // console.log(err, '失败的响应')
//     Toast(err.response.data.message)
//   }
//   // 如果配置了失败的拦截器，就表示你在处理异常，
//   // 如果这个函数不返回任何值，表示异常处理完成，后续的逻辑会走正常的逻辑
//   // 如果想要让后续的逻辑 继续失败，需要继续抛出异常，或者返回一个失败的 Promise
//   // 结论：控制响应拦截器处理函数是否处理成功，就看返回值
//   // 1. 如果 throw 异常，或者 return 失败的 Promise 那么就表示处理失败
//   // 2. 反之，就表示处理成功
//   // throw err
//   // Promise.reject 方法 可以快速创建一个 Promise 实例
//   return Promise.reject(err)

//   // 练习：
//   // return 1 => 成功
//   // return new Error('msg') => 成功
//   // return '请求失败' => 成功
//   // throw '请求成功' => 失败
//   // return Promise.resolve(1) => 成功
//   // return Promise.reject(2) => 失败
//   // 没写 return => 成功
// })

// axiosInstance.interceptors.response.use((res) => {
//   console.log('响应拦截器-成功处理函数-1')
//   return res
// }, (err) => {
//   console.log('响应拦截器-错误处理函数-1')
//   throw err
// })

// axiosInstance.interceptors.response.use((res) => {
//   console.log('响应拦截器-成功处理函数-2')
//   return res
// })

// axiosInstance.interceptors.response.use((res) => {
//   console.log('响应拦截器-成功处理函数-3')
//   return res
// })

// 配置请求拦截器
axiosInstance.interceptors.request.use((config) => {
  // config 是请求配置对象

  // 一定要返回请求配置对象，不然，axios 就不知道要发啥！往哪里发！

  // 统一注入token：
  // 所有的请求在发出去之前，都会先进入请求拦截器成功处理函数，在这里，可以对请求配置做调整
  // 当 本地存储中 有 token 的时候，才需要加到请求头中
  const token = getToken()
  if (token) {
    config.headers.Authorization = 'Bearer ' + token
  }
  return config // 最终的请求配置对象
})

// 此拦截器，处理401问题
// 会有一个默认的成功拦截器，res => res
axiosInstance.interceptors.response.use(undefined, (err) => {
  if (err.response.status === 401) {
    removeToken()
    router.push({ name: 'LoginPage' })
    Toast('登录状态已失效，请重新登录！')
    // 后面【响应拦截器逻辑】以及【页面的逻辑】还需要执行吗？
    // 后面的逻辑都不需要执行了，因为已经处理好了，都跳到登录页面去了
    // 如何中断Promise的链式调用呢？
    // 只需要中断链式调用即可（中断Promise链式调用，因为axios就是基于Promise实现的）
    // 说白了，就是返回一个状态永远是pending的Promise
    return new Promise(() => {})
  }
  // throw err
  return Promise.reject(err)
})

// 此拦截器，做统一错误提示
axiosInstance.interceptors.response.use(undefined, (err) => {
  Toast(err.response.data.message)
  return Promise.reject(err)
})

// 此拦截器，做数据提取，简化页面获取数据的代码
// axios会默认将后端响应的数据包装在data中，页面每次获取时，都需要多.data
// 提取前：后端返回的数据 => res.data
// 提取后：后端返回的数据 => res
axiosInstance.interceptors.response.use(res => res.data)

export default axiosInstance

// 在其他地方要发请求，示例代码：
// import request from '@/utils/request.js'
// request({ method: 'GET', url: '/login' })
